<template>
  <div ref="modalBoxEl">
    <div class="dpro-modal-mask" v-show="visible"></div>
    <div class="dpro-modal-wrap" ref="dproModalWrap" v-show="visible" @click="clickMask">
      <transition name="zoom" appear>
        <div :class="['dpro-modal', { [typeClass]: !!typeClass }]" :style="styles" v-show="visible" @click.stop>
          <div class="dpro-modal-content">
            <!-- 关闭按钮 -->
            <button class="dpro-modal-close" @click="cancel">
              <span class="dpro-modal-close-x">
                <i aria-label="图标: close" class="anticon">
                  <svg viewBox="64 64 896 896" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
                    <path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path>
                  </svg>
                </i>
              </span>
            </button>
            <!-- 标题 -->
            <div class="dpro-modal-header">
              <slot name="title">
                <div class="dpro-modal-title">{{ title }}</div>
              </slot>
            </div>
            <!-- 弹窗内容 -->
            <div class="dpro-modal-body">
              <slot name="default"></slot>
            </div>
            <!-- 弹窗底部 -->
            <div class="dpro-modal-footer" v-if="footer">
              <slot name="footer">
                <dpro-button @click="cancel">取消</dpro-button>
                <dpro-button type="primary">确定</dpro-button>
                <dpro-button type="primary" disabled>disabled</dpro-button>
                <dpro-button disabled>disabled</dpro-button>
              </slot>
            </div>
          </div>
        </div>
      </transition>
    </div>
  </div>
</template>

<script>
import DproButton from "../../button/src/index.vue";
// 一些内置的弹窗类型：default（默认）、largeHeader（头部标题放大居左）
const TYPES = ['default', 'largeHeader'];
export default {
  name: 'DproModal',
  props: {
    // 自定义样式类型
    type: {
      type: String,
      default: 'default'
    },
    // 标题
    title: {
      type: String,
      default: ''
    },
    // 宽度
    width: {
      type: [Number, String],
      default: 520
    },
    // 对话框是否可见
    visible: {
      type: Boolean
    },
    // 关闭时销毁 Modal 里的子元素
    destroyOnClose: {
      type: Boolean,
      default: false
    },
    // 指定 Modal 挂载的 HTML 节点
    getContainer: {
      type: Function,
      default: () => document.body
    },
    // 是否支持键盘 esc 关闭
    // TODO：解决多个弹窗时按esc后全部关闭的问题，应该要从最上面一个弹窗开始按一次关闭一个
    // keyboard: {
    //   type: Boolean,
    //   default: true
    // },
    // 是否展示遮罩
    mask: {
      type: Boolean,
      default: true
    },
    // 点击蒙层是否允许关闭
    maskClosable: {
      type: Boolean,
      default: true
    },
    // 底部内容，当不需要默认底部按钮时，可以设为 :footer="null"
    footer: {
      type: [Boolean, null],
      default: true
    },
  },
  model: {
    prop: 'visible',
    event: 'cancel'
  },
  computed: {
    styles() {
      return `width:${this._width}`
    },
    _width() {
      return typeof(this.width) === 'number' ? `${this.width}px` : this.width;
    },
    typeClass() {
      if(!TYPES.includes(this.type) || this.type === 'default') return '';
      return `dpro-modal-${this.type}`;
    },
    containerNode() {
      return this.getContainer() || document.body;
    },
    modalBoxEl() {
      return this.$refs.modalBoxEl;
    }
  },
  components: {
    DproButton
  },
  data() {
    return {
    }
  },
  watch: {
    visible(val) {
      // console.log('watch-visible', val);
      if (val) {
        // 添加节点
        this.setPopupContainer();
      } else if (!val && this.destroyOnClose) {
        // 移除DOM节点
        this.removeNode();
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.visible && this.setPopupContainer();
    })
    // this.keyboard && document.addEventListener('keydown', this.keyDownHandler)
  },
  beforeDestroy() {
    // document.removeEventListener('keydown', this.keyDownHandler);
    // console.log('beforeDestroy');
    this.removeNode();
  },
  methods: {

    setPopupContainer() {
      // console.log('setPopupContainer', this.containerNode);
      if(!this.containerNode || !this.modalBoxEl) return;
      if(this.modalBoxEl.parentNode === this.containerNode) {
        // 无需调整挂载节点
        // console.log('插入元素已包含，无需重复插入');
        return;
      }
      // 修改挂载节点
      this.modalBoxEl.parentNode && this.modalBoxEl.parentNode.removeChild(this.modalBoxEl);
      this.containerNode.appendChild(this.modalBoxEl);
      // console.log('setPopupContainer-finished');
    },
    removeNode() {
      if(!this.containerNode.contains(this.modalBoxEl)) return;
      this.containerNode?.removeChild(this.modalBoxEl);
    },
    cancel() {
      this.$emit('cancel');
    },
    // 点击蒙层，可由maskClosable参数控制是否可关闭弹窗
    clickMask() {
      this.maskClosable && this.cancel();
    },
    // 支持键盘ESC关闭弹窗
    // keyDownHandler(e) {
    //   if(!this.keyboard) return;
    //   if(e.keyCode === 27) {
    //     this.cancel();
    //   }
    // }
  }
}
</script>

<style lang="less">
@import url(../../styles/variables.less);
.dpro-modal-mask {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1000;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.45);
}
.dpro-modal-wrap {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1000;
  overflow: auto;
  outline: 0;
}
.dpro-modal {
  box-sizing: border-box;
  color: @text-color;
  font-size: 14px;
  line-height: 1.5;
  list-style: none;
  position: relative;
  top: 100px;
  width: auto;
  margin: 0 auto;
  padding: 0 0 24px;
  pointer-events: none;
}
.dpro-modal-content {
  position: relative;
  background-color: @component-background;
  background-clip: padding-box;
  border: 0;
  border-radius: 4px;
  background-image: linear-gradient(180deg, #2D3673 0%, #181D43 100%);
  box-shadow: 0px 4px 16px 0px rgb(0 0 0 / 50%);
  pointer-events: auto;
}
.dpro-modal-close {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 10;
  padding: 0;
  color: var(--disable-text, rgba(255, 255, 255, 0.5));
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  background: transparent;
  border: 0;
  outline: 0;
  cursor: pointer;
  transition: color 0.3s;
  &:hover {
    color: var(--primary-text, #fff);
  }
}
.dpro-modal-close-x {
  display: block;
  width: 32px;
  height: 32px;
  line-height: 32px;
  font-size: 16px;
  text-align: center;
  i{
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
  }
}
.dpro-modal-header {
  height: 32px;
  padding: 4px 24px;
}
.dpro-modal-title {
  font-size: 14px;
  line-height: 24px;
  text-align: center;
  color: var(--primary-text, #fff);
  word-wrap: break-word;
}
.dpro-modal-body {
  padding: 24px;
}
.dpro-modal-footer {
  padding: 24px;
}
.dpro-modal-largeHeader {
  .dpro-modal-header {
    height: auto;
    padding: 30px 50px 20px;
  }
  .dpro-modal-title {
    font-size: 26px;
    line-height: 30px;
    text-align: left;
  }
  .dpro-modal-close {
    right: 20px;
    top: 20px;
  }
  .dpro-modal-close-x {
    width: 40px;
    height: 40px;
    line-height: 42px;
    font-size: 18px;
    border-radius: 20px;
    background-color: var(--divider-color, rgba(255, 255, 255, 0.1));
  }
  .dpro-modal-body {
    padding: 0 50px 24px;
  }
  .dpro-modal-footer {
    padding: 6px 50px 24px;
  }
}
.zoom-enter-active,
.zoom-leave-active {
  transition: all .3s ease;
}
.zoom-enter,
.zoom-leave-to {
  transform: scale(0.1);
  opacity: 0;
}
// .zoom-enter-to,
// .zoom-leave {
//   transform: scale(1);
//   opacity: 1;
// }
</style>